home *** CD-ROM | disk | FTP | other *** search
- {$X+,V-,B-}
- Unit nwSema;
-
- INTERFACE
-
- { Primary functions: Interrupt: comments:
-
- * OpenSemaphore (F220/00)
- * ExamineSemaphore (F220/01)
- * WaitOnSemaphore (F220/02)
- * SignalSemaphore (F220/03)
- * CloseSemaphore (F220/04)
- GetSemaphoreInformation (F217/F3)
-
- Notes: -Functions marked with a '*' are tested and found correct.
-
- }
-
- Uses nwMisc;
-
- Var Result:word;
-
- {C500 [2.0/2.1/3.x]}
- FUNCTION OpenSemaphore( SemName :String; InitVal :Integer;
- VAR SemHandle :LongInt;
- VAR OpenCount :Word ) :Boolean;
- { Semaphores are used for exclusion when record locking is not appropriate }
- { The value is set the first time the semaphore is opened, thereafter you }
- { must use wait semaphore or signal semaphore to change the value }
-
- {C501 [2.0/2.1/3.x]}
- FUNCTION ExamineSemaphore( SemHandle :LongInt;
- VAR Value :Integer;
- VAR OpenCount :Word ) :Boolean;
- { This functions returns the current value and open count of a semaphore.}
- { The semaphore value is decremented for each WAIT_ON_SEMAPHORE, }
- { and incremented for each SIGNAL_SEMAPHORE. A negative semaphore }
- { value indicates the number of processes waiting to use the semaphore. }
- { Count is the number of processes that are using the same semaphore.}
- { The open count is incremented any time a station opens the semaphore }
- { This can be used for controlling the number of users using your software }
- { Value is the current value associates with the semaphore. }
-
- {C502 [2.0/2.1/3.x]}
- FUNCTION WaitOnSemaphore( SemHandle :LongInt;
- Wait_Time :Word ) :Boolean;
- { Decrement the semaphore value and, if it is negative, }
- { wait until it becomes non-negative or until a }
- { timeout occurs. }
-
- {C503 [2.0/2.1/3.x]}
- FUNCTION SignalSemaphore(SemHandle:LongInt) : Boolean;
- { Increment the semaphore value and release if waiting. If any stations }
- { are waiting, the station that has been waiting the longest will be }
- { signalled to proceed }
-
- {C504 [2.0/2.1/3.x]}
- FUNCTION CloseSemaphore(SemHandle:LongInt) : Boolean;
- { Decrement the open count of a semaphore.}
- { When the open count goes to zero, the semaphore is destroyed. }
- { In other words: if the requesting process is the last process to have
- this semaphore open, the semaphore is deleted.}
-
-
- IMPLEMENTATION {=============================================================}
-
- uses dos;
-
- {F:C500 [2.x/3.x]}
- FUNCTION OpenSemaphore(SemName : String; InitVal : Integer;
- VAR SemHandle : LongInt;
- VAR OpenCount : Word) : Boolean;
- Var Regs:Registers;
- BEGIN
- WITH Regs
- DO BEGIN
- IF (InitVal < 0) OR (InitVal > 127)
- THEN BEGIN
- Result:=$FF; { Invalid Semaphore Value }
- OpenSemaphore := False; { InitVal must be between 0 and 127 }
- Exit;
- END;
- IF (SemName[0]>#127) { Semaphore must not exceed 127 chars }
- THEN BEGIN
- Result:=$FE; { Invalid Semaphore name Length }
- OpenSemaphore := false;
- Exit;
- END;
- AH := $C5; { Semaphore function }
- AL := $00; { Sub-Function 0 = open }
- DS := Seg(SemName); { DS:DX points to name }
- DX := Ofs(SemName); { Byte 0 = length 0..127 }
- CL := InitVal; { Initial Value 0..127 }
-
- MsDos(Regs); { Give it to Int 21h }
-
- OpenCount := BL; { Number of users using this semaphore }
- Result:=AL;
- OpenSemaphore := (AL = 0); { OK if AL comes back as 0 }
- { FEh Invalid Semaphore Name Length}
- { FFh Invalid Semaphore Value }
- SemHandle:=MakeLong(CX,DX); { CX:DX holds the semaphore handle }
- END; { with Regs do }
- END; {Function Open_Semaphore }
-
-
- {F:C501 [2.x/3.x]}
- FUNCTION ExamineSemaphore(SemHandle:LongInt;
- VAR Value : Integer;
- VAR OpenCount : Word ) : Boolean;
- { The semaphore value that comes back in CL is the count from the open call }
- { DL represents the current open count - the open count is incremented }
- { anytime a station opens the semaphore this can be used for controlling }
- { the number of users using your software }
- Var Regs:Registers;
- BEGIN
- WITH Regs
- DO BEGIN
- AH := $C5; { Semaphore function call }
- AL := 1; { Sub-Function 1 = examine }
- CX := HiLong(SemHandle);
- DX := LowLong(SemHandle);
-
- MsDos(Regs); { Give it to DOS }
-
- Value := CX; { Semaphore value in CX }
- OpenCount := DL; { Number using this semaphore }
- Result := AL; { AL = $FF invalid handle }
- ExamineSemaphore := (AL = 0); { AL = 0 means OK }
- END;
- END; { function Examine_Semaphore }
-
- {F:C502 [2.x/3.x]}
- FUNCTION WaitOnSemaphore( SemHandle : LongInt;
- Wait_Time : Word ) : Boolean;
- { Decrement the semaphore value and wait if it is negative. If negative,}
- { the workstation will wait until it becomes non-negative or until a }
- { timeout occurs. }
- Var regs:registers;
- BEGIN
- WITH Regs
- DO BEGIN
- AH := $C5; { Semaphore function call }
- AL := 2; { Sub-Function 2 = wait }
- BP := Wait_Time; { In 1/18 seconds, 0 = No wait }
- CX := HiLong(SemHandle);
- DX := LowLong(SemHandle);
-
- MsDos(Regs); { Give it to DOS }
-
- Result:=AL;
- WaitOnSemaphore := (AL = 0); { AL = $00 means OK,
- $FE timeout failure,
- $FF Invalid handle }
- END;
- END; { function Wait_Semaphore }
-
- {C503 [2.x/3.x]}
- FUNCTION SignalSemaphore(SemHandle:LongInt) : Boolean;
- { Increment the semaphore value and release if waiting. If any stations}
- { are waiting, the station that has been waiting the longest will be }
- { signalled to proceed }
- Var Regs:Registers;
- BEGIN
- WITH Regs
- DO BEGIN
- AH := $C5; { Semaphore function call }
- AL := 3; { Sub-Function 3 = signal }
- CX := HiLong(SemHandle);
- DX := LowLong(SemHandle);
-
- MsDos(Regs); { Give it to DOS }
-
- Result:=AL;
- SignalSemaphore := (AL = 0); { AL = $00 means OK, else
- $01 overflow ( value > 127 ) or
- $FF Invalid handle }
- END;
- END; { function Signal_Semaphore }
-
- {C504 [2.x/3.x]}
- FUNCTION CloseSemaphore(SemHandle:LongInt) : Boolean;
- { Decrement the open count of a semaphore. When the open count goes }
- { to zero, the semaphore is destroyed. }
- Var Regs:Registers;
- BEGIN
- WITH Regs
- DO BEGIN
- AH := $C5; { Semaphore function call }
- AL := 04; { Sub-Function 4 = close }
- CX := HiLong(SemHandle);
- DX := LowLong(SemHandle);
-
- MsDos(Regs); { Give it to DOS }
-
- Result:=AL;
- CloseSemaphore := (AL = 0); { AL = 0 means OK, FF: Invalid handle }
- END;
- END; { function Close_Semaphore }
-
-
-
- {E3E1 [2.1x/2.2]
- GET CONNECTION'S SEMAPHORES
- AH = E3h subfn E1h
- DS:SI -> request buffer (see below)
- ES:DI -> reply buffer (see below)
- Return: AL = status
- 00h successful
- C6h no console rights
- Notes: this function is supported by Advanced NetWare 2.1+
- the calling workstation must have console operator privileges
- SeeAlso: AH=E3h/SF=C8h,AH=E3h/SF=DBh,AH=E3h/SF=DFh,AH=E3h/SF=E2h
-
- Format of request buffer:
- Offset Size Description
- 00h WORD 0005h (length of following data)
- 02h BYTE E1h (subfunction "Get Connection's Semaphores")
- 03h WORD (big-endian) logical connection number
- 05h WORD (big-endian) last record seen (0000h on first call)
-
- Format of reply buffer:
- Offset Size Description
- 00h WORD (call) size of following results record (max 1FEh)
- 02h WORD next request record (place in "last record" field on next call)
- 04h BYTE number of records following
- 05h var array of Semaphore Information Records
-
- Format of Semaphore Information Record:
- Offset Size Description
- 00h WORD (big-endian) open count
- 02h BYTE semaphore value (-128 to 127)
- 03h BYTE task number
- 04h BYTE lock type
- 05h BYTE length of semaphore's name
- 06h N BYTEs semaphore's name
- 14 BYTEs filename}
-
-
- {E3E2 [2.1x/2.2]
- GET SEMAPHORE INFORMATION
- AH = E3h subfn E2h
- DS:SI -> request buffer (see below)
- ES:DI -> reply buffer (see below)
- Return: AL = status
- 00h successful
- C6h no console rights
- Notes: this function is supported by Advanced NetWare 2.1+
- the calling workstation must have console operator privileges
- SeeAlso: AH=E3h/SF=C8h,AH=E3h/SF=E1h
-
- Format of request buffer:
- Offset Size Description
- 00h WORD length of following data (max 83h)
- 02h BYTE E2h (subfunction "Get LAN Driver's Configuration Information")
- 03h WORD (big-endian) last record seen (0000h on first call)
- 05h BYTE length of semaphore's name (01h-7Fh)
- 06h N BYTEs semaphore's name
-
- Format of reply buffer:
- Offset Size Description
- 00h WORD (call) size of following results buffer (max 1FEh)
- 02h WORD next request record (place in "last record" on next call)
- 0000h if no more
- 04h WORD (big-endian) number of logical connections opening semaphore
- 06h BYTE semaphore value (-127 to 128)
- 07h BYTE number of records following
- 08h var array of Semaphore Information records (see below)
-
- Format of Semaphore Information:
- Offset Size Description
- 00h WORD (big-endian) logical connection number
- 02h BYTE task number}
-
- {F217/F3 [3.11+]}
- Function GetSemaphoreInformation(SemaName:string;
- {i/o:} Var ReqRecordNbr:Integer;
- {out:} Var openCount:word;
- Var semValue:byte;
- Var connections:TconnectionList):boolean;
-
- { This call returns information about a single semaphore. The
- values returned are similiar to those returned in the old
- version of this call. This function may be called iteratively
- to return all of the connection information for the specified
- semaphore. }
- { 2.x: ?? if there are no more records, ReqRecordNbr is set to 0... }
- { need console rights to do this.. }
- { The function returns the connectionNumbers and taskNumbers as words.
- for the sake of compatibilty, they are returned as bytes. Not too many
- >250 user licences floating around.. I hope.. }
- Var req:record
- len :word; {lo-hi !}
- subF :byte;
- lastRec :word; {hi-lo, initially 0 }
- _semaName:string; { max len=128 }
- end;
- reply:record
- nextRec :word; {hi-lo }
- _OpenCount :word; {hi-lo }
- _semValue :byte;
- { ?? Opencount:byte en semvalue:word ?? }
- NumberOfRecords:word; {hi-lo }
- _connTask:array[1..100] of record
- connNbr, {hi-lo !}
- taskNbr:word; {hi-lo !}
- end;
- end;
- regs:registers;
- t:byte;
- BEGIN
- With req
- do begin
- subF:=$F3;
- if ReqRecordNbr=-1
- then lastRec:=0 { correct false initial value.}
- else lastRec:=swap(ReqRecordNbr); {force hi-lo}
- _semaName:=semaName; UpString(_semaName);
- if semaName[0]>#127 then _semaName[0]:=#127;
- len:=ord(semaName[0])+6;
- end;
- With regs
- do begin
- ax := $f217;
- ds:=SEG(req); si := OFs(req);
- cx:=sizeOf(req);
- es:=SEG(reply); di := OFs(reply);
- dx:=sizeOf(reply);
- MsDos(regs);
- result:=al;
- end;
-
- If result=0
- then with reply
- do begin
- FillChar(connections,sizeOf(connections),#0);
- for t:=0 to swap(NumberOfRecords) { <= 100, force lo-hi }
- do begin
- if _connTask[t].connNbr<=$FF
- then connections[t]:=hi(_connTask[t].connNbr); {= LO}
- end;
- Opencount:=swap(_opencount); { force lo-hi }
- ReqRecordNbr:=swap(nextRec); { force lo-hi }
- semValue:=_semValue;
- end;
-
- GetSemaphoreInformation:=(result=0);
- end;
-
-
- {F2/ [2.15c+]
- Function ( {i/o:} {out: :boolean;
-
- Var req:record
- len :word;
- subF :byte;
-
- end;
- reply:record
-
- end;
- regs:registers;
- BEGIN
- With req
- do begin
- subF:=
-
- len:=
- end;
- With regs
- do begin
- ax := $f217;
- ds:=SEG(req); si := OFs(req);
- cx:=sizeOf(req);
- es:=SEG(reply); di := OFs(reply);
- dx:=sizeOf(reply);
- MsDos(regs);
- result:=al;
- end;
-
- If result=0
- then with reply
- do begin
-
-
- end;
-
- :=(result=0);
- end;}
-
- BEGIN
- END.